package com.zhou.org.common;

import com.zhou.framework.common.SpringFactory;
import com.zhou.framework.util.SessionUtil;
import com.zhou.framework.util.SettingUtil;
import com.zhou.util.StringTool;
import com.zhou.framework.jwt.model.LoginUser;
import com.zhou.org.dao.Right;
import com.zhou.org.dao.SysMenu;
import com.zhou.org.dao.User;
import com.zhou.org.dto.MenuQueryDto;
import com.zhou.org.service.ISysMenuService;
import com.zhou.org.service.OrgService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

@Slf4j
@Component
public class MenuCache implements ApplicationRunner {

    private static ISysMenuService menuService;
    public MenuCache(ISysMenuService service) {
        menuService = service;
    }

    private static Map<String,MenuUrlPattern> urlMap = null;
    private static List<MenuUrlPattern> dynamicList = null;

    private static final Integer LOCK = 0;
    public static void reloadMenu(){
        synchronized (LOCK){
            urlMap = new HashMap<>(20);
            dynamicList = new ArrayList<>(5);
            List<SysMenu> menuList = menuService.selectList(new MenuQueryDto());
            for(SysMenu map : menuList){
                if(StringTool.isNotBlank(map.getPath()) && Objects.equals(map.getMenuType(),EnumConstant.TYPE_INTF)){

                    MenuUrlPattern pattern = MenuUtil.getDynamicUrlPattern(map);
                    if(pattern.getPattern() == null){
                        urlMap.put(pattern.getOriginUrl(),pattern);
                    }else{
                        dynamicList.add(pattern);
                    }
                }
            }
        }
    }

    public static String getUri(HttpServletRequest request){
        String url = request.getRequestURI();
        String contextPath = request.getContextPath();
        if(contextPath.length() > 0 && url.startsWith(contextPath)){
            url = url.substring(contextPath.length());
        }
        if(!url.startsWith("/")){
            url = "/" + url;
        }
        if(!"/".equals(url)){
            int index ;
            if((index = url.indexOf("?")) != -1){
                url = url.substring(0,index);
            }
        }
        return url;
    }

    public static String getUrlName(HttpServletRequest request){
        String url = getUri(request);
        if(!"/".equals(url)){
            MenuUrlPattern pattern = urlMap.get(url);
            if(pattern != null){
                return pattern.getMenuName();
            }
        }
        return null;
    }

    public static boolean checkRequest(HttpServletRequest request){
        String url = getUri(request);
        if(!"/".equals(url)){
            int index ;
            if((index = url.indexOf("?")) != -1){
                url = url.substring(0,index);
            }
            if(!MenuUtil.isIgnoreUrl(url)){
                LoginUser user = SessionUtil.getCurrentUserSafe();
                if(user!= null){
                    User safe = user.getUser();
                    MenuUrlPattern pattern = urlMap.get(url);
                    if(pattern == null){
                        for (MenuUrlPattern p : dynamicList) {
                            if(p.match(url)){
                                pattern = p;
                                break;
                            }
                        }
                    }
                    if(pattern != null && !isAdminUser(safe.getOrgId())){
                        Map<String,Right> rights = RightUtil.getRightMap(RightKeyEnum.MENU,"YES",safe.getOrgId());
                        String objectKey = String.valueOf(pattern.getMenuId());
                        Right right = rights.get(objectKey);
                        return right != null && right.getReject() == 0;
                    }
                    return true;
                }
            }
        }

        return true;
    }

    private static boolean isAdminUser(int orgId){
        int adminOrgId = SettingUtil.getAdminOrgId();
        if(adminOrgId > 0){
            OrgService service = SpringFactory.getBean(OrgService.class);
            //缓存中查找下级orgId
            List<Integer> ids = service.getChildDistinctUserOrgId(adminOrgId);
            return ids.contains(orgId);
        }
        return false;
    }

    @Override
    public void run(ApplicationArguments args) throws Exception {
        reloadMenu();
        log.info("菜单缓存成功");
    }
}
